{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Connecting to Hardware"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SUMMARY**: *In this lab, you'll learn how to setup and connect to your ChipWhisperer hardware. We'll also cover how to build firmware for your target microcontroller, how to capture power traces, and how to communicate with target devices.*\n",
    "\n",
    "*All the API calls we'll be using here are documented on the [ChipWhisperer readthedocs page](https://chipwhisperer.readthedocs.io/en/latest/scope-api.html), so feel free to open it in another tab and follow along there as well.*\n",
    "\n",
    "**LEARNING OUTCOMES:**\n",
    "* Setting up your ChipWhisperer Hardware\n",
    "* Using the ChipWhisperer Python API to connect to your hardware\n",
    "* Communication with the target\n",
    "* Capturing a power trace\n",
    "\n",
    "## Prerequisites\n",
    "\n",
    "Hold up - before continuing, ensure you have done the following:\n",
    "\n",
    "* ☑ Validated your setup using the [ChipWhisperer Setup Test](./ChipWhisperer%20Setup%20Test.ipynb) notebook.\n",
    "* ☑ Run through the Jupyter introduction."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Physical Setup"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### CW-Husky with CW313/SAM4S\n",
    "\n",
    "The only connections you need to make are with the 20-pin connector and the two SMA cables. The only settings to confirm are that JP2 is set to T-GPIO4 and that JP1 and JP4 are connected:\n",
    "\n",
    "<img src=\"img/cwhusky.jpg\" alt=\"CW-Husky Plugged In\" width=500>\n",
    "\n",
    "For the tutorials, you should use `PLATFORM='CWHUSKY'`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ChipWhisperer-Nano\n",
    "\n",
    "The ChipWhisperer-Nano is a single-board device. It includes the capture hardware, along with a built in STM32F0 target. To use this target, simply plug in the device, then go get a drink to reward yourself:\n",
    "\n",
    "<img src=\"img/cwnano.jpg\" alt=\"CW-Nano Plugged In\" width=400>\n",
    "\n",
    "For the tutorials, you should use `PLATFORM='CWNANO'`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ChipWhisperer-Lite (Single Board)\n",
    "\n",
    "The ChipWhisperer-Lite is a single-board device. It includes the capture hardware, along with a built in STM32F3 or XMEGA target. To use this target, simply plug in the device:\n",
    "\n",
    "<img src=\"img/cwlite_plugged.jpg\" alt=\"CW-Lite Plugged In\" width=400>\n",
    "\n",
    "If you have an STM32F3 target, you should use `PLATFORM='CWLITEARM'` for the tutorials. If you have an XMEGA target, you should use `PLATFORM='CWLITEXMEGA'`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ChipWhisperer-Lite (2-Part Version)\n",
    "\n",
    "The ChipWhisperer-Lite 2-Part version includes the ChipWhisperer-Capture along with an XMEGA target. You need to attach the SMA & IDE cables, then plug in the USB cable:\n",
    "\n",
    "<img src=\"img/cw_2part.jpg\" alt=\"CW-Lite 2-Part Connected\" width=500>\n",
    "\n",
    "For the tutorials, you should use `PLATFORM='CWLITEXMEGA'`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ChipWhisperer-Lite (Capture + UFO), Includes SCAPACK-L1/SCAPACK-L2\n",
    "\n",
    "This package uses a ChipWhisperer-Lite Capture board, along with a CW308 UFO target board. You'll need to attach the CW308 board to your ChipWhisperer-Lite Capture, and plug in your choosen target board. The suggested target for most tutorials is the `CW308_STM32F3` - you can tell this target by checking the part number on the chip, look for a `STM32F303`.\n",
    "\n",
    "Here is an overview photo of the target plugged in:\n",
    "\n",
    "<img src=\"img/cwcapture_ufo.jpg\" alt=\"CW-Lite Plugged Into UFO\" width=600>\n",
    "\n",
    "If using the F3 for the tutorials, you should use `PLATFORM='CW308_STM32F3'`.\n",
    "\n",
    "See Section below on UFO Target Settings."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ChipWhisperer-Pro\n",
    "\n",
    "This package uses a ChipWhisperer-Pro Capture device, along with a CW308 UFO target board. You'll need to attach the CW308 board to your ChipWhisperer-Pro Capture, and plug in your choosen target board. The suggested target for most tutorials is the `CW308_STM32F3` - you can tell this target by checking the part number on the chip, look for a `STM32F303`.\n",
    "\n",
    "Here is an overview photo of the business end of the CW-Pro plugged into the UFO board. You'll need to also plug in the USB-A cable, and possibly the DC power jack (2.1mm DC power jack, 5V comes from either USB or wall adapter). Earlier hardware revisions always needed the DC power jack, later hardware revisions will use USB power (but high-power targets still need extra juice).\n",
    "\n",
    "<img src=\"img/cwpro_ufo.jpg\" alt=\"CW-Pro Plugged In\" width=500>\n",
    "\n",
    "If using the F3 for the tutorials, you should use `PLATFORM='CW308_STM32F3'`.\n",
    "\n",
    "See Section below on UFO Target Settings."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### UFO Target Settings\n",
    "\n",
    "The UFO Board comes by default with working settings for most targets. A summary of the default jumper settings is included below for you, see the product documentation for more details.\n",
    "\n",
    "<img src=\"img/cwufo_stm32f3.jpg\" alt=\"UFO Board\" width=500>\n",
    "\n",
    "#### UFO Default Settings\n",
    "\n",
    "* J1  - 3.3V (CW3.3V)\n",
    "* J3  - HS2/OUT\n",
    "* J14 - FILT/FILT_LP/FILT_HP\n",
    "* J16 - No connection\n",
    "\n",
    "* S1 -  ON\n",
    "\n",
    "* 3.3V SRC - J1/CW\n",
    "* VADJ SRC - 3.3V\n",
    "* 1.2V, 1.8V, 2.5V, 3.3V, LDO SRC - J1/CW\n",
    "* 5V SRC - J1/CW"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### CW-Lite single board: XMEGA vs ARM\n",
    "\n",
    "If you are unsure which single-part version you have, the following shows both boards. Note the only difference is the target section on the right.\n",
    "\n",
    "<img src=\"img/cwlitearm_vs_cwlitexmega.jpg\" alt=\"CW-Lite XMEGA vs Arm Board\" width=500>\n",
    "\n",
    "If you have an STM32F3 target, you should use `PLATFORM='CWLITEARM'` for the tutorials. If you have an XMEGA target, you should use `PLATFORM='CWLITEXMEGA'`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Connecting to ChipWhisperer\n",
    "\n",
    "Now that your hardware is all setup, we can now learn how to connect to it. We can connect to the ChipWhisperer with:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import chipwhisperer as cw\n",
    "scope = cw.scope()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "By default, ChipWhisperer will try to autodetect the type of device your're running (CWLite/CW1200 or CWNano), see API documentation for manually specifying the scope type. If you have multiple ChipWhisperer devices connected, you'll need to specify the serial number of the device you want to connect to:\n",
    "\n",
    "```python\n",
    "scope = cw.scope(sn='<some long string of numbers>')\n",
    "```\n",
    "\n",
    "For more information, see the [API section on readthedocs](https://chipwhisperer.readthedocs.io/en/latest/scope-api.html).\n",
    "\n",
    "Connecting to the target device is simple as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target = cw.target(scope, cw.targets.SimpleSerial) #cw.targets.SimpleSerial can be omitted"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll only be discussing the default target type, which is SimpleSerial. Other targets, like the CW305, will be covered in hardware specific demos. \n",
    "\n",
    "Some sane default settings can be set using:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.default_setup()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "which from its [documentation](https://chipwhisperer.readthedocs.io/en/latest/scope-api.html#chipwhisperer.scopes.OpenADC.default_setup) you can see does the following for the CWLite/CW1200:\n",
    "\n",
    "* Sets the scope gain to 45dB\n",
    "* Sets the scope to capture 5000 samples\n",
    "* Sets the scope offset to 0 (aka it will begin capturing as soon as it is triggered)\n",
    "* Sets the scope trigger to rising edge\n",
    "* Outputs a 7.37MHz clock to the target on HS2\n",
    "* Clocks the scope ADC at 4\\*7.37MHz. Note that this is *synchronous* to the target clock on HS2\n",
    "* Assigns GPIO1 as serial RX\n",
    "* Assigns GPIO2 as serial TX"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And that's it! Your ChipWhisperer is now setup and ready to attack a target. \n",
    "\n",
    "**NOTE: You'll need to disconnect the scope/target before connecting again, like you would in another notebook. This can be done with `scope.dis()` and `target.dis()`**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Building and Uploading Firmware\n",
    "\n",
    "The next step in attacking a target is to get some firmware built and uploaded onto it. Most firmware for most ChipWhisperer targets can be built using our build system, provided you have the correct compiler installed (see https://chipwhisperer.readthedocs.io/en/latest/installation.html for info about compilers).\n",
    "\n",
    "Firmware must be built on the command line. Luckily, thanks to Jupyter, we can run a command within a notebook as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%bash\n",
    "cd ../firmware/mcu/simpleserial-base/\n",
    "make PLATFORM= CRYPTO_TARGET=NONE"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You should see a big list of `PLATFORM`s to build for. We left the `PLATFORM` blank in the command above, so the build system instead printed a list of supported platforms. Fill in your platform, rerun the build command, and your firmware should be successfully built.\n",
    "\n",
    "Continuing on, there's two possible ways to upload firmware to your target:\n",
    "\n",
    "1. ChipWhisperer has built in support for XMEGA, STM32F*, AVR, and SAM4S bootloaders. These can be used as follows"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#cw.program_target(scope, cw.programmers.XMEGAProgrammer, \"path/to/firmware.hex\")\n",
    "#cw.program_target(scope, cw.programmers.STM32FProgrammer, \"path/to/firmware.hex\")\n",
    "#cw.program_target(scope, cw.programmers.AVRProgrammer, \"path/to/firmware.hex\")\n",
    "#cw.program_target(scope, cw.programmers.SAM4SProgrammer, \"path/to/firmware.hex\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "2. For other targets, you'll need to use an external programmer or a debugger to flash the firmware onto the target. \n",
    "\n",
    "Whatever your case, upload the firmware we built earlier to the target device. Next we'll be learning how to capture power traces and communicate with the target."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Communication with the Target\n",
    "\n",
    "Communication with targets, which is done through the `SimpleSerial target` object we got earlier, is grouped into two categories:\n",
    "\n",
    "1. Raw serial via `target.read()`, `target.write()`, `target.flush()`, etc. \n",
    "\n",
    "1. SimpleSerial commands via `target.simpleserial_read()`, `target.simpleserial_write()`, `target.simpleserial_wait_ack()`, etc.\n",
    "\n",
    "The firmware we uploaded uses the simpleserial protocol (https://wiki.newae.com/SimpleSerial), so we'll start off with simpleserial. Later, we'll use the raw serial commands to send the same messages.\n",
    "\n",
    "If you check the simpleserial-base firmware (`simpleserial-base.c`) you'll find that for the simpleserial `'p'` command, the target will echo back the command. Let's try that out now:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "msg = bytearray([0]*16) #simpleserial uses bytearrays\n",
    "target.simpleserial_write('p', msg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's check if we got a response:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(target.simpleserial_read('r', 16))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It also has a `'k'` command. Try sending that now:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That command doesn't return anything to us, but it should ack and give us an error return:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(target.simpleserial_wait_ack()) #should return 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Simpleserial messages generally take the form:\n",
    "\n",
    "```python\n",
    "command_character + ascii_encoded_bytes + '\\n'\n",
    "```\n",
    "\n",
    "For our first command, `command_character='p'` and `ascii_encoded_bytes=\"00\"*16` (keep in mind this isn't a binary `0x00`, it's ASCII `\"00\"`, which has a binary value of `0x3030`). Try resending the `'p'` command from earlier using `target.write()`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "target.write('p' + ) #fill in the rest here"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A simple `target.read()` will return all the characters that have been sent back from the target so far. Let's see what the device returned to us:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "recv_msg = \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "recv_msg += target.read() #you might have to run this block a few times to get the full message\n",
    "print(recv_msg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The simpleserial commands are usually sufficient for taking to simpleserial firmware, but you'll need the raw serial commands for some of the other labs."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## SimpleSerial 2\n",
    "\n",
    "As of ChipWhisperer 5.4, a new target communication protocol, SimpleSerial 2 is available. It has a number of advantages over the old SimpleSerial protocol:\n",
    "\n",
    "1. Data is unencoded binary (except for byte stuffing) instead of ACII encoded, meaning far more data can be sent per packet (just under double)\n",
    "1. It's got a command and subcommand field that get passed to the target callback functions, meaning more can be done per packet. For example, the simpleserial-aes firmware has been modified to allow plaintext, key, and/or mask to be set with a single packet.\n",
    "1. It's got a length field, meaning the same target commands can take different length packets depending on the situation. This, for example, allows both plaintext and key (or only one) to be send with the same command in simpleserial-aes.\n",
    "1. It's got an 8-bit CRC (0xA6) for data integrety.\n",
    "1. Frames are consistant overhead byte stuffed (COBS). This makes it easy to reset communication (done simply by sending two 0x00 bytes) and helps catch malformed length bytes.\n",
    "\n",
    "It is, however, a more complicated protocol. You can use it by compiling firmware with `SS_VER=SS_VER_2_0` and using `cw.targets.SimpleSerial2`. In `sca101` and `fault101`, it can be used by setting `SS_VER='SS_VER_2_0'` when setting `PLATFORM` and `SCOPETYPE`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Capturing Traces\n",
    "\n",
    "Now that the target's programmed and we know how to communicate with it, let's start recording some power traces! To capture a trace:\n",
    "\n",
    "1. Arm the ChipWhisperer with `scope.arm()`. It will begin capturing as soon as it is triggered (which in our case is a rising edge on `gpio4`.\n",
    "1. `scope.capture()` will read back the captured power trace, blocking until either ChipWhisperer is done recording, or the scope times out. Note that the error return will tell you whether or not the scope timed out. It does not return the captured scope data.\n",
    "1. You can read back the captured power trace with `scope.get_last_trace()`.\n",
    "\n",
    "`simpleserial_base` will trigger the ChipWhisperer when we send the `'p'` command. Try capturing a trace now:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.arm()\n",
    "target.simpleserial_write('p', msg)\n",
    "## fill in the rest..."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ChipWhisperer also has a `capture_trace()` convience function that:\n",
    "\n",
    "1. Optionally sends the `'k'` command\n",
    "1. Arms the scope\n",
    "1. Sends the `'p'` command\n",
    "1. Captures the trace\n",
    "1. Reads the return `'r'` message\n",
    "1. Returns a `Trace` class that groups the trace data, `'p'` message, the `'r'` message, and the `'k'` message\n",
    "\n",
    "It isn't always the best option to use, but it's usually sufficient for most simpleserial applications"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conclusion\n",
    "\n",
    "And that's it! You should be all ready to continue on to SCA101 (or any other of our courses).\n",
    "\n",
    "We've glossed over some stuff here, so consult the [API documentation](https://chipwhisperer.readthedocs.io/en/latest/scope-api.html) or ask on our [forums](https://forum.newae.com) if you get stuck.\n",
    "\n",
    "As a final step, we should disconnect from the hardware so it doesn't stay \"in use\" by this notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "scope.dis()\n",
    "target.dis()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## ChipWhisperer-Husky\n",
    "\n",
    "While the ChipWhisperer-Husky has many new features, its API has been designed to keep most basic tasks the same, especially with power analysis. You should be able to go through SCA101 without learning anything Husky specific and fault101 will cover any Husky specific things you need to know. That being said, you may still find it helpful to refer to the `demos/husky` folder, starting with [01 - Introduction to ChipWhisperer-Husky.ipynb](demos/husky/01%20-%20Introduction%20to%20ChipWhisperer-Husky.ipynb) to learn more about its advanced features."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
